var yyyy_MM_dd_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
var yyyyMMdd_PARSER = new SimpleDateFormat("yyyyMMdd");
var yyyy_MM_dd_HH_mm_ss_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
var indexHtml = "";
var the_bill_day ="18";
var appJS = "";
var needReLogin = true;
var RASKEY = "";
var payment_due_date_f = null;
var v6_ceb_credit_java_funcs = {
    openHomePage : function(){
        indexHtml =RequestUtil.get("https://xyk.cebbank.com/mall/login?target=/mycard/home/home.htm");
        for(var i=0;i<=10;i++){
            Thread.sleep(1000);
            indexHtml =RequestUtil.get("https://xyk.cebbank.com/mall/login?target=/mycard/home/home.htm");
            logger.info("任务：{},开始获取登录的必要参数，获取app.js",context.get(LUA_TASK_KEY));
            Thread.sleep(1000);
            var appjs_url = "https://xyk.cebbank.com/assets/scripts/app-" + getGroupByIndex("/assets/scripts/app-([^.js]*)", indexHtml, 1) + ".js";
            appJS = RequestUtil.get(appjs_url);
            storeDataToFile(context, appJS, "app.js")
            if(!appJS.contains("/images/home/error.jpg")){
                logger.info("成功获取到appjs")
                break;
            }
        }
        storeDataToFile(context, indexHtml, "loginHtml.html")
    },
    checkProxyAvailable : function() {
        logger.info("任务：{}，光大银行信用卡入口检测代理是否可用",context.get(LUA_TASK_KEY));
        //判断是否代理异常的function
        var isCorrectFunc = function(indexHtml){
            var doc = Jsoup.parse(indexHtml);
            return (doc!=null && doc.select("#login")!=null);
        }
        //获取异常信息的方法function
        var getErrorMsgFunc = function(indexHtml) {
            return "代理ip异常";
        }
        //返回信息
        return assertTrueOrThrowException(indexHtml, isCorrectFunc, getErrorMsgFunc)
    },
    checkControlAvailable:function(){
        logger.info("任务：{}，不需要安装控件",context.get(LUA_TASK_KEY));
        return true;
    },
    /**
     * 检查网站是否可用
     * @returns {*}
     */
    checkTargetWebsiteAvailable: function(){
        logger.info("任务taskKey = {}, 进入检查光大银行网站是否可用方法", context.get(LUA_TASK_KEY));
        return true;
    },
    needResetEnvironment:function(){
        return equals(context.get("currentErrorCode"), BALO_99602_50)
    },
    login:function(){
        if(needReLogin){
            logger.info("任务：{}，进入到光大信用卡登录过程",context.get(LUA_TASK_KEY));
            logger.info("--------------------------------------LOGIN START---------------------------------------------")
            RASKEY = getGroupByIndex("payPrimaryKay:\"([^\"]*?)\"", appJS, 1);
            if(StringUtils.isBlank(RASKEY)){
                //可能会多空格
                RASKEY = getGroupByIndex("payPrimaryKay: \"([^\"]*?)\"", appJS, 1);
            }
            logger.info("任务：{},参数获取完成，获取到的动态加密参数为:{}",context.get(LUA_TASK_KEY),RASKEY);
            storeDataToFile(context, indexHtml, "loginHtml.html")

            //------------------------------------判断用户的登录方式是否正确，获取登录用户名密码-------------------------------------
            logger.info("任务：{},从上下文中获取登录参数，判断登录方式是否正确",context.get(LUA_TASK_KEY));
            var loginTypeMsg = "true";
            if (equals(LoginType.CARDNO.toString(),context.get(LUA_TASK_LOGIN_TYPE))) {
                logger.info("任务：{}，登录方式为卡号登录",context.get(LUA_TASK_KEY))
                var cardNo = getLoginParams(context)[0];
                context.put("name", cardNo);
            } else if (equals(LoginType.IDCARD.toString(),context.get(LUA_TASK_LOGIN_TYPE))) {
                logger.info("任务：{},登录方式为身份证号登录",context.get(LUA_TASK_KEY))
                var certNo = getLoginParams(context)[0];
                context.put("name", certNo);
                //将获取的身份证号中的x或者X或者a或者A替换为""
                var checkCard = certNo.replaceAll("x|X|a|A", "");
                logger.info("任务：{}，判断身份证是否符合正则表达式,certNo：{}，结果：{}",context.get(LUA_TASK_KEY),certNo,isStringToNumber(checkCard));
                if (certNo.length() > 18 || !isStringToNumber(checkCard)) {
                    loginTypeMsg = "尚未注册或无此用户";
                }
            } else {
                logger.info("任务：{}，登录方式错误",context.get(LUA_TASK_KEY));
                loginTypeMsg = "该银行不支持卡号登录方式";
            }
            //判断登录方式流程正确性
            var isLoginTypeCorrectFunc = function(loginTypeMsg){
                if(loginTypeMsg.equals("true")){
                    return true
                }else{
                    return false
                }
            }
            //获取登录方式的错误信息
            var getLoginTypeErrMsg = function (loginTypeMsg) {
                return loginTypeMsg;
            }
            assertTrueOrThrowException(loginTypeMsg, isLoginTypeCorrectFunc, getLoginTypeErrMsg);
            logger.info("任务：{},登录参数获取成功，登录方式正确",context.get(LUA_TASK_KEY));

            //---------------------------------输入图片验证码--发送短信-----------------------------------------------
            var dynamic = getImgAndSendSms();
            storeDataToFile(context, dynamic, "dynamic1.txt")
            if(strIsJSON(dynamic)){
                //说明发送频繁
                var object = JSON.parseObject(dynamic);
                var dataStr = object.getString("data");
                var sleep_time = 0;
                if(object.getString("status").equals("200") && /^[\d+]+$/.test(object.getJSONObject("data").getString("result")) && parseInt(object.getJSONObject("data").getString("result")) < 60){
                    sleep_time = (parseInt(object.getJSONObject("data").getString("result"))) * 1000;
                }else if(dataStr.contains(",")){
                    var data = JSON.parseObject(dataStr).getString("result");
                    var timeArr = data.split(",");
                    if(parseInt(timeArr[0]) < 60){
                        sleep_time = parseInt(timeArr[0]) * 1000
                    }
                }
                if(sleep_time > 0){
                    logger.info("任务：【{}】，发送短信需要休眠【{}】毫秒",context.get(LUA_TASK_KEY),sleep_time)
                    logger.info("开始休眠【{}】===============================",context.get(LUA_TASK_KEY))
                    Thread.sleep(sleep_time)
                    logger.info("结束休眠【{}】===============================",context.get(LUA_TASK_KEY))
                    //休眠够了之后再重新调用一次
                    dynamic = getImgAndSendSms();
                    storeDataToFile(context, dynamic, "dynamic2.txt")
                }
            }
            //判断短信验证码发送的流程正确性 获取短信验证码时会验证身份证号或者其余的信息格式是否正确，根据返回的结果判断是否输入的信息是否正确
            var isSendSmsCorrectFunc = function (dynamic) {
                //如果返回的status码是200表示登录成功
                if(strIsJSON(dynamic)){
                    var object = JSON.parseObject(dynamic);
                    var status = object.getString("status");
                    if (status!=null && status.equals("200")) {
                        var res = object.getJSONObject("data").getString("result")
                        if(res.contains(",")){
                            var time = res.split(",");
                            if(parseInt(time[0]) < 60){
                                return false;
                            }
                        }else{
                            if(parseInt(res) < 60){
                                return false;
                            }
                        }
                        return true;
                    }else{
                        return false;
                    }
                }else{
                    return false;
                }
            }
            //获取图片验证码和短信验证码的错误信息
            var getSendSmsErrMsg = function (dynamic) {
                if(strIsJSON(dynamic)){
                    var object = JSON.parseObject(dynamic);
                    var res = object.getJSONObject("data").getString("result")
                    if(res.contains(",")){
                        var time = res.split(",");
                        if(object.getString("status").equals("200") && /^[\d+]+$/.test(time[0]) && parseInt(time[0]) < 60){
                            return "短信验证码发送频繁，请稍后再试";
                        }
                    }else{
                        if(object.getString("status").equals("200") && /^[\d+]+$/.test(object.getJSONObject("data").getString("result")) && parseInt(object.getJSONObject("data").getString("result")) < 60){
                            return "短信验证码发送频繁，请稍后再试";
                        }
                    }
                }
                return StringUtils.isNotBlank(dynamic) ? dynamic.trim().replace(/[\r\n]/g, '') : "";;
            }
            assertTrueOrThrowException(dynamic, isSendSmsCorrectFunc, getSendSmsErrMsg);
            logger.info("任务：{},图片验证码校验成功，短信验证码发送成功",context.get(LUA_TASK_KEY));
        }

        //-----------------------------------------开始校验短信验证码是否正确---------------------------------------
        logger.info("任务：{}，开始获取并校验用户输入的短信验证码是否正确",context.get(LUA_TASK_KEY));
        var smsCheckMsg = "";
        var waitstartTime = System.currentTimeMillis();
        var  verifyMessage = waitSmsCodeBySeconds(context,120);
        var waitEndTime = System.currentTimeMillis();
        logger.info("任务【{}】，等待用户短信时长【{}】",context.get(LUA_TASK_KEY),waitEndTime-waitstartTime)

        var startTime = System.currentTimeMillis();
        logger.info("任务【{}】，收到用户短信，当前时间戳【{}】",context.get(LUA_TASK_KEY),startTime)
        logger.info("任务：{},获取到的短信验证码为：{}",context.get(LUA_TASK_KEY),verifyMessage)
        //校验短信验证码的格式是否正确的流程，错误的话不继续向下进行
        var isSmsLengthCorrectFunc = function (verifyMessage) {
            return StringUtils.isNotBlank(verifyMessage) && verifyMessage.length === 6;
        }
        var getSmsLengthErrMsg = function (verifyMessage) {
            needReLogin = false;
            return "短信验证码错误";
        }
        assertTrueOrThrowException(verifyMessage, isSmsLengthCorrectFunc, getSmsLengthErrMsg);
        logger.info("任务：{},用户输入的短信验证码格式符合要求",context.get(LUA_TASK_KEY));

        logger.info("任务：{}，开始加载js对密码进行rsa加密",context.get(LUA_TASK_KEY));
        var scriptEngineManager = new ScriptEngineManager();
        var eg = scriptEngineManager.getEngineByName("JavaScript");
        eg.eval("load('js/ceb/ceb.js')");
        var readyState =  eg.eval("RSATEST('" + verifyMessage + "','" + RASKEY + "')");
        logger.info("任务：{}，密码加密之后：{}",context.get(LUA_TASK_KEY), readyState);
        var code =  context.get("code");
        var name =  context.get("name");
        Thread.sleep(1000);
        var map = new HashMap();
        map.put("code", code);
        map.put("password", readyState);
        map.put("target", "/mycard/home/home.htm");
        map.put("userName", name);
        //登录
        var loginHtml = RequestUtil.post("https://xyk.cebbank.com/mall/api/user/login?t=" + Math.floor(Math.random() * 10000000), map);
        storeDataToFile(context, loginHtml, "smsCheck.html")
        logger.info("任务：{}，短信验证码校验完成，官网返回：{}",context.get(LUA_TASK_KEY),loginHtml);
        //校验短信验证码是否正确的流程
        var smsCheckResultCorrectFunc = function (loginHtml) {
            if(strIsJSON(loginHtml)){
                var object = JSON.parseObject(loginHtml);
                var status = object.getString("status");
                //判断是否为200，如果为200表示登录成功，否则登录失败
                if (StringUtils.isNotBlank(status) && status.equals("200")) {
                    return true;
                } else {
                    return false;
                }
            }else{
                return false;
            }
        }
        //获取短信验证码校验的错误提示信息方法
        var getSmsCodeCheckErrMsg = function (loginHtml) {
            if (StringUtils.isEmpty(loginHtml)) {
                return "短信验证码超时"
            }else if(loginHtml.contains("BBBBBBB")){
                var error_count = loginHtml.trim().replace(/[\r\n]/g, '').substring(7,8);
                needReLogin = false;
                return "校验动态密码失败，您已检验失败" + error_count + "次";
            }else if(loginHtml.contains("CCCCCCC")){
                needReLogin = true;
                return "校验动态密码失败，已超过5次，请重新获取";
            }else if(loginHtml.contains("DDDDDDD")){
                needReLogin = true;
                return "校验动态密码超时，15分钟之内有效，请重新获取";
            }else if(loginHtml.contains("EEEEEEE")){
                needReLogin = true;
                return "校验动态密码超时，请重新获取";
            }else if(loginHtml.contains("GGGGGGG")){
                needReLogin = true;
                return "动态密码已失效，请重新获取";
            }else if(loginHtml.contains("FFFFFFF")){
                needReLogin = true;
                return "图片验证码错误";
            } else{
                return StringUtils.isNotBlank(loginHtml) ? loginHtml.trim().replace(/[\r\n]/g, '') : "";
            }
        }
        var endTime = System.currentTimeMillis();
        logger.info("任务【{}】，用户登录结束，从收到短信到登录结束用时【{}】",context.get(LUA_TASK_KEY),(endTime - startTime))
        logger.info("------------------------------------------------LOGIN END-------------------------------------------------")
        assertTrueOrThrowException(loginHtml, smsCheckResultCorrectFunc, getSmsCodeCheckErrMsg);
    },
    crawl:crawl,
    exitLogin: function () {}
}

/**
 * 获取图片校验码和发短信单独抽取出来，以便重试
 */
function getImgAndSendSms(){
    logger.info("任务：{},开始获取图片验证码base64并由打码平台自动打码",context.get(LUA_TASK_KEY));
    var captcha = RequestUtil.getAsBytes("https://xyk.cebbank.com/mall/api/captcha?" + Math.floor(Math.random() * 10000000));
    context.put(TASK_IMG_BYTES, captcha);
    context.put(TASK_IMG_REGEX,"[0-9a-zA-Z]{4}");
    var code = waitImgCodeBySecondsByJs(context,60,true,3)
    logger.info("任务：{},图片验证码自动打码完成，code：{}",context.get(LUA_TASK_KEY),code);

    //---------------------------------判断图片验证码  发送短信验证码--------------------------------------
    logger.info("任务：{},开始校验图片验证码，如果校验成功将会自动发送短信验证码",context.get(LUA_TASK_KEY));
    var parametersMap = new HashMap();
    var name =  context.get("name");
    parametersMap.put("name", name);
    parametersMap.put("code", code.toLowerCase());
    var dynamic = RequestUtil.post("https://xyk.cebbank.com/mall/api/usercommon/dynamic", parametersMap);
    context.put("code", code.toLowerCase());
    logger.info("任务：{}，图片验证码校验/短信验证码发送，返回结果：{}", context.get(LUA_TASK_KEY) ,dynamic);
    return dynamic;
}

/** ---------------------------------------------------------------
 * ------------------------ 抓取数据 -------------------------------
  ----------------------------------------------------------------*/
function crawl() {
    //获取登录后的界面 -- 休眠一秒 -- 404重试防止网络问题获取失败 -- 最多十次
    getAfterLoginFirstHtml();
    //解析登录后首页
    parseAfterLoginFirstHtml();
    //获取卡片信息
    getCardInfoHtml();
    //解析获取卡列表信息
    parseCardInfoHtml();
    //获取到卡列表，开始调用通用方法构造表头
    context.put(keys.CRED_CARD_SIZE,context.get("ceb_card_list").size());
    createData();
    var data_list = context.get(ALL_DATA);

    for (var i = 0; i < context.get("ceb_card_list").size(); i++) {
        // 获取对应的creditCardAllData
        var creditCardAllData = data_list.get(i);
        //初始化creditCardAllData -- 设置卡号，开户行，卡号后四位，户名
        initCreditAllDataFun(creditCardAllData,context.get("ceb_card_list").get(i));
        // 基本信息
        getBaseInfoHtml();
        //获取账户汇总信息请求参数
        paraseBaseParams();
        //抓取账户基本信息
        getUserAccountInfoHtml(i);
        //获取账户信息
        paraseUserHtml(creditCardAllData);

        //获取账单页面
        getBillsHtml(i);
        //解析已出账单外层列表信息 -- 获取到账单日期列表
        parseBillsHtml();
        if(context.get("ceb_have_bills_info") != null && context.get("ceb_have_bills_info")){
            var monthList = context.get("ceb_bill_month_list");
            for(var j = 0;j < monthList.size();j++){
                var bill_moth = monthList.get(j);
                //获取该月份的账单信息
                getEveryMonthBillHtml(i,j+1,bill_moth);
                if (context.get("ceb_every_month_bill_html").contains("对不起！") && context.get("ceb_every_month_bill_html").contains("未知错误")) {
                    logger.info("taskKey={},光大银行，页面返回未知错误，跳过改月账单，继续进行",context.get(LUA_TASK_KEY))
                    continue;
                }
                //解析账单页面
                paraseBillHtml(bill_moth,creditCardAllData);
            }
        }
        // 抓取未出账单页面
        getUnBillHtml(i);
        //获取未出账单的billdata
        var billAllData = getUNDoneBillAllDataHeaderData(creditCardAllData);
        //初始化billdata
        var cal = Calendar.getInstance();
        getWithOutBillMoth(cal);
        initUnBillAllData(billAllData);

        var index = 1;
        var num = 1;
        var shopping_sheets = new ArrayList();
        var installments = new ArrayList();
        //解析未出账单页面
        paraseUnBillHtml(shopping_sheets, index);
        var unbillMap = new HashMap();
        //获取未出账单的请求的参数
        var flag = paraseunbillParams(unbillMap);
        //根据判断查询未出账单信息是否失败
        while (flag) {
            getUnBillHtmlOther(i,num,unbillMap)
            //判断查询账单信息是否失败
            if (context.get("ceb_unbill_html").contains("查询未出账单信息失败")) {
                flag = false;
                break;
            }
            //解析未出账单页面
            paraseUnBillHtml(shopping_sheets, index);
            //获取未出账单的请求参数
            flag = paraseunbillParams(unbillMap);
            num++;
        }

        cal.setTime(cal.getTime());
        cal.add(Calendar.MONTH, -1);
        var currdate = cal.getTime();
        var currmoth = yyyy_MM_dd_FORMAT.format(currdate);
        currmoth = currmoth.substring(0, 7);
        handleWithOutBillData(billAllData,currmoth,creditCardAllData,shopping_sheets);
        handleBillAllDataInstallMentsFee(creditCardAllData)
       // paraseunBills(creditCardAllData, i, bills, context.get("ceb_account_map"),creditCardAllData,cal);
    }
    //处理未出账单的还款日
    handleWithOutBillDueDate(context.get(ALL_DATA));

}

//处理已出账单中的分期问题
function handleBillAllDataInstallMentsFee(creditCardAllData) {
    try {
        logger.info("任务【{}】，开始处理账单中的分期问题",context.get(LUA_TASK_KEY));
        var bills = creditCardAllData.getBills();
        for (var i = 0;i < bills.size();i++) {
            var billData = bills.get(i);
            var shoping_sheets = billData.getShoppingSheets();
            var installments = billData.getInstallments();
            var ins = null;
            for(var j = 0;j < shoping_sheets.size();j++){
                var expense = shoping_sheets.get(j);
                print(expense.getDescription())
                if(expense.getDescription() != null && (expense.getDescription().contains("交易分期 (分期)") || expense.getDescription().contains("账单分期分月 (分期)") || expense.getDescription().contains("账单分期 (分期)"))){
                    ins = new Installment();
                    ins.setInstallmentDesc(expense.getDescription());//分期描述
                    ins.setHandingfeeDesc("");//分期手续费描述
                    ins.setBillId(UUID.randomUUID().toString());//分期编号
                    ins.setTransDate(expense.getTransDate());//交易时间
                    ins.setPostDate(expense.getPostDate());//记账日期
                    ins.setShoppingsheetId(UUID.randomUUID().toString());//消费记录
                    ins.setInstallmentType("BILL");//分期类型
                    ins.setTransferFee(null);//转账手续费
                    ins.setTotalMonth(null);//总分期数
                    ins.setCurrentMonth(null);//当前分期数
                    ins.setAmountMoney(expense.getAmountMoney());//本期金额
                    ins.setCurrencyType("CNY");//币种
                    ins.setHandingFee(null);//本期手续费
                    ins.setTransferfeeDesc("");
                }

                if(expense.getDescription() != null && ins!=null && (expense.getDescription().contains("分期付款手续费"))){
                    ins.setHandingfeeDesc(expense.getDescription());//分期手续费描述
                    ins.setHandingFee(expense.getAmountMoney());//本期手续费
                    installments.add(ins)
                }
            }

            //处理等额分期的情况
            for(var j = 0;j < shoping_sheets.size();j++) {
                var expense = shoping_sheets.get(j);
                print(expense.getDescription())
                if(expense.getDescription()!=null && (expense.getDescription().contains("等额分期手续费"))){
                    for(var k = 0;k < installments.size();k++){
                        var installment = installments.get(k)
                        if(installment.getInstallmentDesc()!=null && installment.getHandingFee()== null && (installment.getInstallmentDesc().contains("账单交易分期(手续费分月等额支付)"))){
                            installment.setHandingfeeDesc(expense.getDescription());//分期手续费描述
                            installment.setHandingFee(expense.getAmountMoney());//本期手续费
                        }
                    }
                }
            }
        }
        logger.info("任务【{}】，处理账单中的分期问题完成",context.get(LUA_TASK_KEY));
    } catch (e) {
        logger.error("任务【{}】,处理账单中的分期问题完成异常【{}】",context.get(LUA_TASK_KEY),e);
        statCaughtExceptionByJS(context, e);
    }

}

function getUnBillHtmlOther(i,num,unbillMap) {
    logger.info("任务【{}】,光大信用卡开始获取未出账单信息",context.get(LUA_TASK_KEY))
    //获取未出账单页面
    var unbillHtml = RequestUtil.post("https://xyk.cebbank.com/mycard/bill/unprintbill-query.htm", unbillMap);
    //保存页面
    storeDataToFile(context, unbillHtml, i + "_unbillHtml_" + num + ".html")
    context.put("ceb_unbill_html",unbillHtml)
    logger.info("任务【{}】,光大信用卡获取未出账单信息完成",context.get(LUA_TASK_KEY))
}

function handleWithOutBillDueDate(data_list) {
    for (var i=0;i<data_list.size();i++){
        var credAllData = data_list.get(i);
        var bills = credAllData.getBills();
        for(var j = 0;j < bills.size();j++){
            var billAllData = bills.get(j);
            if(billAllData.getBillType().equals("UNDONE") && billAllData.getPaymentDueDate() == null){
                billAllData.setPaymentDueDate(payment_due_date_f);
            }
        }

    }
}

/**
 * 功能描述:获取登录后的首页页面，如果遇到网络问题404，重试
 * @auther: SSD
 * @date: 2018/7/25 10:35
 */
function getAfterLoginFirstHtml() {
    logger.info("任务【{}】,光大银行开始进行登陆后页面抓取",context.get(LUA_TASK_KEY));
    Thread.sleep(1000);
    logger.info("任务【 {} 】-延迟两秒",  context.get(LUA_TASK_KEY));
    //获取登录后的页面
    var firstHtml = RequestUtil.get("https://xyk.cebbank.com/mycard/home/home.htm");
    //重试10次，防止网络原因导致失败
    for(var i = 0;i < 10;i++){
        if(firstHtml.contains("Error 404--Not")){
            logger.info("任务【 {} 】-重试链接",context.get(LUA_TASK_KEY));
            Thread.sleep(1000);
            firstHtml = RequestUtil.get("https://xyk.cebbank.com/mycard/home/home.htm");
        }else{
            logger.info("任务【 {} 】-重试成功",context.get(LUA_TASK_KEY));
            break;
        }
    }
    //保存页面
    storeDataToFile(context, firstHtml, "firstHtml.html")
    context.put("ceb_first_html",firstHtml);
    logger.info("任务【{}】,光大银行登陆后页面抓取完成",context.get(LUA_TASK_KEY));
}
/**
 * 功能描述:解析登录后首页内容，获取 name_on_card 存入context 方便其他地方调用
 * @auther: SSD
 * @date: 2018/7/25 10:41
 */
function parseAfterLoginFirstHtml() {
    logger.info("任务【{}】,光大银行登录后页面解析开始",context.get(LUA_TASK_KEY));
    try {
        var name_on_card = "";
        var firstHtml = context.get("ceb_first_html");
        var firstDoc = Jsoup.parse(firstHtml);
        //获取持卡人姓名
        if (firstDoc != null) {
            var strong = firstDoc.select("#logined > p > strong");
            if (strong != null) {
                name_on_card  = strong.text().replaceAll(",", "")
            }
        }
        context.put("ceb_name_on_card",name_on_card);
        logger.info("任务【 {} 】-延迟一秒,继续进行",  context.get(LUA_TASK_KEY));
        Thread.sleep(1000);
        logger.info("任务【{}】,光大银行登录后页面解析完成",context.get(LUA_TASK_KEY));
    } catch (e) {
        logger.error("任务【{}】,光大银行登录后页面解析异常，异常【{}】", context.get(LUA_TASK_KEY), e);
        statCaughtExceptionByJS(context, e);
    }
}

/**
 * 功能描述:获取卡片信息的页面--并保存页面
 * @auther: SSD
 * @date: 2018/7/25 14:07
 */
function getCardInfoHtml() {
    logger.info("任务【{}】,光大信用卡，开始抓取卡片信息",context.get(LUA_TASK_KEY));
    //获取卡片信息
    var cardsHtml = RequestUtil.get("https://xyk.cebbank.com/mycard/home/acclist.htm?num=" + Math.floor(Math.random() * 10000000));
    //保存页面
    storeDataToFile(context, cardsHtml, "cardsHtml.html")
    context.put("ceb_card_info_html",cardsHtml);
    logger.info("任务【{}】,光大信用卡，卡片信息抓取完成",context.get(LUA_TASK_KEY));
}

function parseCardInfoHtml() {
    logger.info("任务【{}】,光大信用卡，开始解析卡片列表信息",context.get(LUA_TASK_KEY));

    var cardsHtml = context.get("ceb_card_info_html");
    var doc = Jsoup.parse(cardsHtml);
    var tab99;
    if(doc != null){
        tab99 = doc.select("[class='tab99']");
    }
    if (doc == null || tab99 == null || tab99.size() == 0) {
        logger.error("任务【{}】,光大信用卡，登陆后获取到卡列表长度为0，未获取到卡片信息",context.get(LUA_TASK_KEY));
        throw new BankException(BALO_20304_30, errorMsgMap.get(BALO_20304_30));
    }
    context.put("ceb_card_list",tab99);
    logger.info("任务【{}】,光大信用卡，卡列表信息解析完成",context.get(LUA_TASK_KEY));

}

/**
 * 功能描述:初始化creditAllData的一些属性
 * @auther: SSD
 * @date: 2018/7/25 14:25
 */
function initCreditAllDataFun(creditCardAllData,tab) {
    logger.info("任务【{}】,光大银行信用卡，开始初始化creditCardAllData",context.get(LUA_TASK_KEY));
    try {
        var name_on_card = context.get("ceb_name_on_card");
        creditCardAllData.setCashBalance(null);
        creditCardAllData.setNameOnCard(name_on_card.replaceAll(",", ""));
        var a = tab.select("#a4");
        var full_card_num_temp = tab.select("td") == null ? "" : (tab.select("td")).get(0).text();
        var full_card_num = "";
        if (a != null) {
            full_card_num = a.attr("onclick") == null ? full_card_num_temp :  ((a.attr("onclick").split("'")).length >= 2 ? (a.attr("onclick").split("'"))[1] : full_card_num_temp);
        }
        context.put("ceb_full_card_num",full_card_num);
        var card_num = full_card_num.substring(full_card_num.length() - 4, full_card_num.length());
        context.put("shopping_card_num",card_num);
        creditCardAllData.setFullCardNum(full_card_num);
        creditCardAllData.setCardNum(card_num);
        creditCardAllData.setOpenBank("光大银行");//开户银行
        logger.info("任务【{}】,光大银行信用卡，初始化creditCardAllData完成",context.get(LUA_TASK_KEY));
    } catch (e) {
        logger.error("任务【{}】,光大银行信用卡，初始化creditCardAllData异常【{}】",context.get(LUA_TASK_KEY),e);
        statCaughtExceptionByJS(context, e);
    }
}

/**
 * 功能描述:
 * @auther: SSD
 * @date: 2018/7/25 15:21
 */
function getBaseInfoHtml() {
    logger.info("任务【{}】,光大银行信用卡开始抓取基本信息",context.get(LUA_TASK_KEY));
    var baseHtml = RequestUtil.get("https://xyk.cebbank.com/mycard/bill/info.htm");
    storeDataToFile(context, baseHtml, "baseHtml.html")
    context.put("ceb_base_html",baseHtml);
    logger.info("任务【{}】,光大银行信用卡基本信息抓取完成",context.get(LUA_TASK_KEY));
}

/**
 * 功能描述:拼接账户汇总信息请求参数
 * @auther: SSD
 * @date: 2018/7/25 15:35
 */
function paraseBaseParams() {
    try {
        logger.info("任务【{}】,光大银行信用卡开始进行账户信息汇总参数拼接",context.get(LUA_TASK_KEY))
        var baseHtml = context.get("ceb_base_html")
        var cardNum = context.get("ceb_full_card_num")
        var postdata = new HashMap();
        var userDoc = Jsoup.parse(baseHtml);
        //var ss = userDoc.getElementsByTag("form");
        //var billinfoform = userDoc.getElementById("type");
        //var scriptList = billinfoform.getAllElements();
        var inputs = userDoc.select("input:not([name='type']):not([name='cardno'])");
        for each(var input in inputs) {
            postdata.put(input.attr("name"), input.attr("value"));
        }
        postdata.put("type", "lb");
        postdata.put("cardno", cardNum);
        context.put("ceb_post_data",postdata);
        logger.info("任务【{}】,光大银行信用卡开始进行账户信息汇总参数拼接",context.get(LUA_TASK_KEY))
    } catch (e) {
        logger.error("任务【{}】,光大银行信用卡账户信息汇总参数拼接异常【{}】",context.get(LUA_TASK_KEY),e)
        statCaughtExceptionByJS(context, e);
    }
}

/**
 * 功能描述:抓取账户信息
 * @auther: SSD
 * @date: 2018/7/25 15:47
 */
function getUserAccountInfoHtml(i) {
    logger.info("任务【{}】,光大银行信用卡，开始获取账户基本信息页面",context.get(LUA_TASK_KEY));
    var userHtml = RequestUtil.post("https://xyk.cebbank.com/mycard/bill/info.htm", context.get("ceb_post_data"));
    storeDataToFile(context, userHtml, i + "_userHtml.html")
    context.put("ceb_user_account_html",userHtml);
    logger.info("任务【{}】,光大银行信用卡，获取账户基本信息页面完成",context.get(LUA_TASK_KEY));
}

/**
 * 功能描述:解析账户基本信息
 * @auther: SSD
 * @date: 2018/7/25 16:43
 */
function paraseUserHtml(creditCardAllData) {
    logger.info("任务【{}】,光大银行信用卡解析账户信息开始",context.get(LUA_TASK_KEY))
    try {
        var map = new HashMap();
        var userHtml = context.get("ceb_user_account_html");
        //解析账户信息
        var doc = Jsoup.parse(userHtml);
        var trs = doc.select("#formshow > td > table > tbody > tr");
        logger.info("");
        for each (var tr in trs) {
            var tds = tr.select("td");
            if (tds.size() == 0) {
                continue;
            }
            //取其td标签的值并判断
            var td = tds.get(0).text();
            //根据描述取出对应的值
            if (td.contains("信用额度")) {
                creditCardAllData.setCreditLimit(getBigDecimalByString(tds.get(1).text()));
                map.put("credit_limit", tds.get(1).text());
            } else if (td.contains("预借现金额度")) {
                creditCardAllData.setCashLimit(getBigDecimalByString(tds.get(1).text()));
                context.put("cash_limit",getBigDecimalByString(tds.get(1).text()))
            } else if (td.contains("实际可用额度")) {
                if (tds.get(1).text().contains("超限")) {
                    creditCardAllData.setBalance(getBigDecimalByString(tds.get(1).text().replaceAll("超限|元", "")).negate());
                } else {
                    creditCardAllData.setBalance(getBigDecimalByString(tds.get(1).text()));
                }
            } else if (td.contains("账单日")) {

            } else if (td.contains("到期还款日")) {
                map.put("payment_due_date", tds.get(1).text());
            } else if (td.contains("本期账单应还款额")) {
                map.put("new_balance", tds.get(1).text().replaceAll("账单分期", ""));
            } else if (td.contains("本期最小还款额")) {
                map.put("min_payment", tds.get(1).text());
            }
        }
        context.put("ceb_account_map",map);
        logger.info("任务【{}】,光大银行信用卡解析账户信息完成",context.get(LUA_TASK_KEY))
    } catch (e) {
        logger.error("任务【{}】,光大银行信用卡解析账户信息完成异常【{}】",context.get(LUA_TASK_KEY),e)
        statCaughtExceptionByJS(context, e);
    }
}

/**
 * 功能描述:获取已出账单外层列表信息
 * @auther: SSD
 * @date: 2018/7/26 9:49
 */
function getBillsHtml(i) {
    logger.info("任务【{}】,光大银行信用卡开始获取已出账单页面",context.get(LUA_TASK_KEY));
    //获取账单页面
    var billsHtml = RequestUtil.get("https://xyk.cebbank.com/mycard/bill/havingprintbill-query.htm");
    //保存页面
    storeDataToFile(context, billsHtml, i + "billsHtml.html")
    context.put("ceb_bills_html",billsHtml);
    logger.info("任务【{}】,光大银行信用卡获取已出账单页面完成",context.get(LUA_TASK_KEY));
}

/**
 *
 * 功能描述:解析已出账单外层列表信息 -- 返回下面tr数组
 * @auther: Test
 * @date: 2018/7/26 9:50
 */
function parseBillsHtml() {
    logger.info("任务【{}】,光大银行信用卡开始解析已出账单外层列表信息",context.get(LUA_TASK_KEY))
    var monthList = new ArrayList();
    try {
        var billsHtml = context.get("ceb_bills_html");
        if (billsHtml.contains("对不起！") && billsHtml.contains("未知错误")) {
            logger.error("任务"+  context.get(LUA_TASK_KEY) + "账单信息-:无账单记录");
            context.put("ceb_have_bills_info",false);
        } else {
            context.put("ceb_have_bills_info",true);
            //解析账单页面
            var billsDoc = Jsoup.parse(billsHtml);
            var tab_one = billsDoc.select("[class='tab_one']");
            if(tab_one !=null && tab_one.size()>=1){
                var tab = tab_one.get(0);
                //获取其tr属性
                var trs = tab.select("tr");
                if(trs!=null){
                    for (var j = trs.size() - 1; j >= 1; j--) {
                        var tr = trs.get(j);
                        var tds = tr.select("td");
                        var td0 = tds.get(0);
                        var scriptE = td0.getElementsByTag("script").get(0);
                        var scriptList = scriptE.dataNodes();
                        var datanode = scriptList.get(0);
                        var script = datanode.toString();
                        var format = getGroupByIndex("formatDate8to10\\('\\d{8}", script, 0);
                        if (StringUtils.isNotEmpty(format)) {
                            //账单月份
                            var bill_moth = getGroupByIndex("\\d{8}", format, 0);
                            monthList.add(bill_moth);
                        }
                    }
                }
            }
        }
        context.put("ceb_bill_month_list",monthList);
        logger.info("任务【{}】,光大银行信用卡解析已出账单外层列表信息完成",context.get(LUA_TASK_KEY))
    } catch (e) {
        logger.error("任务【{}】,光大银行信用卡解析已出账单外层列表信息异常【{}】",context.get(LUA_TASK_KEY),e)
        statCaughtExceptionByJS(context, e);
    }
}
/**
 * 功能描述:获取各月份的账单信息
 * @auther: SSD
 * @date: 2018/7/26 10:50
 */
function getEveryMonthBillHtml(i,j,bill_moth) {
    logger.info("任务【{}】,光大银行信用卡获取账单详细，月份【{}】",context.get(LUA_TASK_KEY),bill_moth)
    Thread.sleep(1000)
    var billHtml = RequestUtil.get("https://xyk.cebbank.com/mycard/bill/billquerydetail.htm?statementDate=" + bill_moth);
    //保存页面
    storeDataToFile(context, billHtml, i + "_billHtml_" + j + ".html")
    context.put("ceb_every_month_bill_html",billHtml);
    logger.info("任务【{}】,光大银行信用卡获取账单详细完成，月份【{}】",context.get(LUA_TASK_KEY),bill_moth)
}
/**
 * 功能描述:抓取未出账单外层列表信息
 * @auther: SSD
 * @date: 2018/7/26 11:39
 */
function getUnBillHtml(i) {
    logger.info("任务【{}】,光大银行信用卡开始获取未出账单页面0",context.get(LUA_TASK_KEY))
    var full_card_num = context.get("ceb_full_card_num");
    //请求未出账单地址
    var unbillsHtml = RequestUtil.get("https://xyk.cebbank.com/mycard/bill/unprintbill.htm");
    //保存页面
    storeDataToFile(context, unbillsHtml, "unbillsHtml.html")
    //请求改卡号的未出账单信息
    var unbillHtml = RequestUtil.get("https://xyk.cebbank.com/mycard/bill/unprintbill-query.htm?ACCT_NBR=" + full_card_num + "&ORG=102");
    //保存页面信息
    storeDataToFile(context, unbillHtml, i + "_unbillHtml_0.html")
    context.put("ceb_unbill_html",unbillHtml);
    logger.info("任务【{}】,光大银行信用卡获取未出账单页面完成0",context.get(LUA_TASK_KEY))
}

function getWithOutBillMoth(cal) {
    var theDay = cal.get(Calendar.DAY_OF_MONTH);
    //判断当前时间是否大于18号，如果大于，未出账单的月份为下月的18号，如果小于等于18号，则为当月的18号
    if(theDay > parseInt(the_bill_day)){
        cal.add(Calendar.MONTH, 1);
    }

    var moth = yyyy_MM_dd_FORMAT.format(cal.getTime());
    context.put("ceb_with_out_bill_moth",moth);
}

/**
 * 功能描述:初始化未出账单的billAllData
 * @auther: SSD
 * @date: 2018/7/26 11:59
 */
function initUnBillAllData(billAllData) {
    logger.info("任务【{}】,光大信用卡初始化未出账单的billAllData",context.get(LUA_TASK_KEY))
    try {
        var map = context.get("ceb_account_map");
        var moth = context.get("ceb_with_out_bill_moth")
        //账单日
        billAllData.setBillDate(yyyy_MM_dd_PARSER.parse(moth.substring(0, 7) + "-" + the_bill_day))
        //账单编号
        billAllData.setBillId(UUID.randomUUID().toString());
        //账单月份
        billAllData.setBillMonth(moth.substring(0, 7));
        //预借现金额度
        billAllData.setCashLimit(context.get("cash_limit"));
        //上期账单金额
        billAllData.setLastBalance(null);
        //上期还款金额
        billAllData.setLastPayment(null);
        //利息
        billAllData.setInterest(null);
        //预借现金额度美元
        billAllData.setUsdCashLimit(null);
        //信用卡额度美元
        billAllData.setUsdCreditLimit(null);
        //利息美元
        billAllData.setUsdInterest(null);
        //上期账单金额美元
        billAllData.setUsdLastBalance(null);
        //上期还款金额美元
        billAllData.setUsdLastPayment(null);
        //最低还款金额美元
        billAllData.setUsdMinPayment(null);
        //本期账单金额美元
        billAllData.setUsdNewBalance(null);
        //本期新增款额美元
        billAllData.setUsdNewCharges(null);
        // billAllData.setNewBalance(getBigDecimalByString(map.get("new_balance")));
        //判断map中的最低还款金额是否为空，来确定最低还款金额的值
        if (map.get("min_payment") != null) {
            billAllData.setMinPayment(getBigDecimalByString(map.get("min_payment")));
        } else {
            billAllData.setMinPayment(null);
        }
        //判断map中的信用卡额度是否为空，来确定信用卡额度的值
        if (map.get("credit_limit") != null) {
            billAllData.setCreditLimit(getBigDecimalByString(map.get("credit_limit")));
        } else {
            billAllData.setCreditLimit(null);
        }
        var cals = Calendar.getInstance();
        //判断map中的还款日是否为空，来确定还款日的值
        if (map.get("payment_due_date") == null || map.get("payment_due_date").equals("")) {
            billAllData.setPaymentDueDate(null);
        } else {
            cals.setTime(yyyy_MM_dd_FORMAT.parse(map.get("payment_due_date")));
            cals.add(Calendar.MONTH, 1);
            var due_date = yyyy_MM_dd_FORMAT.format(cals.getTime());
            payment_due_date_f = yyyy_MM_dd_PARSER.parse(due_date)
            billAllData.setPaymentDueDate(yyyy_MM_dd_PARSER.parse(due_date));
        }
        logger.info("任务【{}】,光大信用卡初始化未出账单的billAllData完成",context.get(LUA_TASK_KEY))
    } catch (e){
        logger.error("任务【{}】,光大信用卡初始化未出账单的billAllData异常【{}】",context.get(LUA_TASK_KEY),e)
        statCaughtExceptionByJS(context, e);
    }

}
/**
 * 判断传入的值是否否则该正则表达式
 * @param str
 * @returns {*}
 */
function isStringToNumber( str) {
    return isMatch("^[0-9]+$",str);
}



/**
 * 解析未出账单
 * @param full_card_num
 * @param i
 * @param bills
 * @param map
 */
function handleWithOutBillData(billAllData,currmoth,creditCardAllData,shopping_sheets) {
    try {
        logger.info("任务【{}】,光大信用卡开始解析未出账单信息",context.get(LUA_TASK_KEY))
        var money = new BigDecimal("0.0");
        for each(var exp in shopping_sheets) {
            //获取消费金额
            var amount = exp.getAmountMoney();
            //如果消费金额为null，则本期新增款额为上文中的money+消费金额
            if(amount==null){
                money = money.add(new BigDecimal("0.0"));
                //如果消费金额不为null或者消费金额为正
            }else if (amount != null && amount.signum() == 1) {
                money = money.add(amount);
            }
        }
        //本期账单金额
        billAllData.setNewBalance(money);
        var bills = creditCardAllData.getBills();
        for each(var billData in bills) {
            if (StringUtils.isNotBlank(billData.getBillMonth()) && currmoth.equals(billData.getBillMonth())) {
                var currBalance = money.add(billData.getNewBalance());
                //本期账单金额
                billAllData.setNewBalance(currBalance);
                //上期账单金额
                billAllData.setLastBalance(billData.getNewBalance());
            }
        }

        //计算上期还款金额,取上期的
        var payment_money = new BigDecimal("0.0");
        for each(var exp in shopping_sheets) {
            //获取消费金额
            var payment_amount = exp.getAmountMoney();
            //根据判断账单金额是否为负值来计算上期还款金额
            if (payment_amount!=null && payment_amount.signum() == -1) {
                payment_money = payment_money.add(payment_amount);
            }
        }
        //上期还款金额
        billAllData.setLastPayment(null);
        billAllData.setMinPayment(null);
        //本期新增款额
        billAllData.setNewCharges(money.compareTo(BigDecimal.ZERO)==0.00 ? null : money);
        billAllData.setShoppingSheets(shopping_sheets);
        logger.info("任务【{}】,光大信用卡解析未出账单信息完成",context.get(LUA_TASK_KEY))
    } catch (e){
        logger.error("任务【{}】,光大信用卡解析未出账单信息异常【{}】",context.get(LUA_TASK_KEY),e)
        statCaughtExceptionByJS(context, e);
    }

}

/**
 * 解析未出账单的页面
 * @param unbillHtml
 * @param shopping_sheets
 * @param index
 */
function paraseUnBillHtml(shopping_sheets,  index) {
    var unbillHtml = context.get("ceb_unbill_html");
    //解析未出账单页面
    var doc = Jsoup.parse(unbillHtml);
    var trs = doc
        .select("body > table > tbody > tr:not(:first-child)");
    for (var i = 0; i < trs.size(); i++) {
        var exp = new Expense();
        var tr = trs.get(i);
        var tds = tr.select("td");
        //获取交易时间
        var trans_date = tds.get(0).text();
        //获取记账日期
        var post_date = tds.get(1).text();
        //获取卡号
        var card_num = tds.get(2).text().replace(/&nbsp;/ig,'');
        if(StringUtils.isBlank(card_num)){
            card_num = context.get("shopping_card_num");
        }
        //获取描述
        var description = tds.get(3).text().replace(/&nbsp;/ig,'');
        //获取其交易金额
        var amount_money = tds.get(4).text();
        //交易时间
        exp.setTransDate(yyyyMMdd_PARSER.parse(trans_date));
        //记账日
        exp.setPostDate(yyyy_MM_dd_PARSER.parse(post_date));
        //卡号
        exp.setCardNum(card_num);
        //币种
        exp.setCurrencyType("CNY");
        //编号
        exp.setId(UUID.randomUUID().toString());
        //描述
        exp.setDescription(description);
        //账户余额
        exp.setBalance(null);

        exp.setTransAddr("");//交易地点
        exp.setTransMethod("");//交易方式
        exp.setTransChannel("");//交易通道
        exp.setRemark("");//备注
        exp.setOppositeCardNo("");//对方卡号
        exp.setNameOnOppositeCard("");//对方持卡人
        exp.setOppositeBank("");//对方银行

        //判断交易金额是存入还是支出，如果是存入交易金额字段为负
        if (amount_money.contains("存入")) {
            exp.setAmountMoney(new BigDecimal(amount_money.replaceAll("存入", "")).negate());
        } else {
            exp.setAmountMoney(new BigDecimal(amount_money));
        }
        //编号
        exp.setOrderIndex(index++);
        //根据描述判断消费类型
        exp.setCategory(classify(description,exp.getAmountMoney()));
        shopping_sheets.add(exp);
    }
}

/**
 * 解析账单页面
 * @param billHtml
 * @param bills
 * @param bill_moth
 */
function paraseBillHtml(bill_moth,creditCardAllData) {
    try {
        logger.info("任务【{}】,光大银行信用卡解析已出账单，月份【{}】完成",context.get(LUA_TASK_KEY),bill_moth)
        var billHtml = context.get("ceb_every_month_bill_html");
        //判断是否有账单记录
        if (billHtml.contains("无账单记录")) {
            logger.error("任务" +  context.get(LUA_TASK_KEY) + "账单信息-" + bill_moth + ":无账单记录");
            return;
        } else if (billHtml.contains("您目前没有登录，请登录后进行此操作")) {
            logger.error("任务" +  context.get(LUA_TASK_KEY) + "账单信息-" + bill_moth + ":无账单记录");
            return;
        }
        //解析账单信息
        var doc = Jsoup.parse(billHtml);
        var billAllData = getDoneBillAllDataHeaderData(creditCardAllData);

        //银行
        var bill_date = doc.select("body > div:nth-child(4) > div:nth-child(2) > table:nth-child(2) > tbody > tr:nth-child(2) > td:nth-child(1)").text();
        if(StringUtils.isNotBlank(bill_date)){
            //账单日
            billAllData.setBillDate(yyyy_MM_dd_PARSER.parse(bill_date.replaceAll("/", "-")));
            the_bill_day = bill_date.substring(8,10)
        }
        var buffer = new StringBuffer(bill_moth.substring(0, 6));
        buffer.insert(4, "-");
        //账单月份
        billAllData.setBillMonth(buffer.toString());
        //还款日
        var payment_due_date = doc
            .select("body > div:nth-child(4) > div:nth-child(2) > table:nth-child(2) > tbody > tr:nth-child(2) > td:nth-child(2)")
            .text();
        if(StringUtils.isNotBlank(payment_due_date)){
            billAllData.setPaymentDueDate(yyyy_MM_dd_PARSER.parse(payment_due_date.replaceAll("/", "-")));
        }
        var scripts = doc
            .select("body > div:nth-child(4) > div:nth-child(2) > table:nth-child(2) > tbody > tr:nth-child(2) > td:nth-child(3) > script");
        //信用卡额度
        var credit_limit = getDataNodeToString(scripts);
        var scriptn = doc
            .select("body > div:nth-child(4) > div:nth-child(2) > table:nth-child(2) > tbody > tr:nth-child(4) > td:nth-child(1) > script");
        //本期账单金额
        var new_balance = getDataNodeToString(scriptn);
        billAllData.setNewBalance(getstringToBigDecimal(new_balance));
        var scriptm = doc
            .select("body > div:nth-child(4) > div:nth-child(2) > table:nth-child(2) > tbody > tr:nth-child(4) > td:nth-child(2) > script");
        //最低还款额度
        var min_payment = getDataNodeToString(scriptm);
        billAllData.setMinPayment(getstringToBigDecimal(min_payment));
        //预借现金额度
        billAllData.setCashLimit(context.get("cash_limit"));
        //信用额度
        billAllData.setCreditLimit(getstringToBigDecimal(credit_limit));
        //上期账单金额
        billAllData.setLastBalance(null);
        //上期还款额度
        billAllData.setLastPayment(null);
        //利息
        billAllData.setInterest(null);
        //预借现金额度美元
        billAllData.setUsdCashLimit(null);
        //信用额度美元
        billAllData.setUsdCreditLimit(null);
        //利息美元
        billAllData.setUsdInterest(null);
        //上期账单金额美元
        billAllData.setUsdLastBalance(null);
        //上期还款额度美元
        billAllData.setUsdLastPayment(null);
        //最低还款额度美元
        billAllData.setUsdMinPayment(null);
        //本期账单金额美元
        billAllData.setUsdNewBalance(null);
        //本期新增款额美元
        billAllData.setUsdNewCharges(null);
        var index = 1;
        var shopping_sheets = new ArrayList();
        var installments = new ArrayList();
        var trs = doc.select("body > div:nth-child(4) > div:nth-child(4) > div:nth-child(2) > table:nth-child(2) > tbody > tr.items > td > table:nth-child(2) > tbody > tr:not(:first-child):not(:nth-child(2))");
        for (var i = 0; i < trs.size() - 1; i++) {
            // logger.info("打印："+i);
            var exp = new Expense();
            var tr = trs.get(i);
            var tds = tr.select("td");
            var trans_date = tds.get(0).text();
            var post_date = tds.get(1).text();
            var card_num = tds.get(2).text().replace(/&nbsp;/ig,'').replace(/\?/ig,"").trim();
            if(StringUtils.isBlank(card_num)){
                card_num = context.get("shopping_card_num");
            }
            var description = tds.get(3).text().replace(/&nbsp;/ig,'').replace(/\?/ig,"").trim();

            var scripta = tds.get(4).select("script").get(0).dataNodes();
            var amount_money = scripta.get(0).toString();
            //exp 中为null的字段要转换成“”
            exp.setTransAddr("");//交易地点
            exp.setTransMethod("");//交易方式
            exp.setTransChannel("");//交易通道
            exp.setRemark("");//备注
            exp.setOppositeCardNo("");//对方卡号
            exp.setNameOnOppositeCard("");//对方持卡人
            exp.setOppositeBank("");//对方银行


            //账户余额
            exp.setBalance(null);
            //交易时间
            exp.setTransDate(yyyyMMdd_PARSER
                .parse(trans_date));
            //记账日期
            exp.setPostDate(yyyyMMdd_PARSER
                .parse(post_date));
            //卡号
            exp.setCardNum(card_num.replaceAll(" || ", ""));
            //描述
            exp.setDescription(description);
            //编号
            exp.setId(UUID.randomUUID().toString());
            //通过匹配正则获取所需字段
            var money = getGroupByIndex(" 账单分期 \\(分期\\) ([^a-zA-Z]+)", description, 1);
            var install = getGroupByIndex("月份账单账单分期([^']*?)期：", description, 1);
            var inttall = getGroupByIndex("月份账单取现分期([^']*?)期：", description, 1);

            var inmtall = getGroupByIndex(" 账单分期分月 \\(分期\\) ([^a-zA-Z]+)", description, 1);
            var inatall = getGroupByIndex("月份账单交易分期\\(手续费分月等额支付\\)([^']*?)期：", description, 1);
            var inztall = getGroupByIndex(" 账单分期 ([0-9]{1,10},[0-9]{3}.[0-9]{1,2}?$)", description, 1);
            var inktall = getGroupByIndex(" 账单分期 (\\d+\\.00)", description, 1);
            var inytall = getGroupByIndex("月份账单邮购分期([^']*?)期：", description, 1);
            var inntall = getGroupByIndex("月份账单自选分期([^']*?)期：", description, 1);
            var inwtall = getGroupByIndex(" 账单分期 (\\d+\\.\\d)", description, 1);
            var infenqi = getGroupByIndex("账单分期 \\(分期\\) ([0-9]{1,10},[0-9]{3}.[0-9]{1,2}?$)",description,1);
            //"账单分期 (分期) 6,905.00

            //账单金额
            var amountMoney;
            //分期月数
            var install_month =null;
            var current_month = null;//当前期数
            if (StringUtils.isNotEmpty(install)
                || StringUtils.isNotEmpty(inttall)) {
                var mon = getGroupByIndex("本期应还款([^，]*?)，", description, 1);
                //exp.setAmountMoney();
                install_month = StringUtils.isNotEmpty(install)? parseInt(install) : parseInt(inttall);
                current_month = install_month - (StringUtils.isNotEmpty(getGroupByIndex("余期为(\\d+)期", description, 1)) ? parseInt(getGroupByIndex("余期为(\\d+)期", description, 1)) : 0);
                amountMoney = new BigDecimal(mon.replaceAll(",", ""))
            } else if (StringUtils.isNotEmpty(money)) {
                //exp.setAmountMoney();
                //install_month = StringUtils.isNotEmpty(install)? parseInt(install) : null;
                amountMoney = new BigDecimal(money.replaceAll(",", ""))
            } else if (StringUtils.isNotEmpty(inmtall)) {
                //exp.setAmountMoney();
                amountMoney = new BigDecimal(inmtall.replaceAll(",", ""));
            } else if (StringUtils.isNotEmpty(inatall)) {
                var mon = getGroupByIndex("本期应还款([^，]*?)，", description, 1);
                install_month = parseInt(inatall)
                current_month = install_month - (StringUtils.isNotEmpty(getGroupByIndex("余期为(\\d+)期", description, 1)) ? parseInt(getGroupByIndex("余期为(\\d+)期", description, 1)) : 0);
                //exp.setAmountMoney();
                amountMoney = new BigDecimal(mon.replaceAll(",", ""));
            } else if (StringUtils.isNotEmpty(inztall)) {
                //exp.setAmountMoney(new BigDecimal(inztall.replaceAll(",", "")));
                amountMoney = new BigDecimal(inztall.replaceAll(",", ""));
            } else if (StringUtils.isNotEmpty(inktall)) {
                var mon = getGroupByIndex(" 账单分期 (\\d+\\.00)", description, 1);
                //exp.setAmountMoney(new BigDecimal(mon.replaceAll(",", "")));
                amountMoney = new BigDecimal(mon.replaceAll(",", ""))
            } else if (StringUtils.isNotEmpty(inytall)) {
                var mon = getGroupByIndex("本期应还款([^，]*?)，", description, 1);
                install_month = parseInt(inytall);
                current_month =install_month - (StringUtils.isNotEmpty(getGroupByIndex("余期为(\\d+)期", description, 1)) ? parseInt(getGroupByIndex("余期为(\\d+)期", description, 1)) : 0);
                //exp.setAmountMoney(new BigDecimal(mon.replaceAll(",", "")));
                amountMoney = new BigDecimal(mon.replaceAll(",", ""))
            } else if (StringUtils.isNotEmpty(inntall)) {
                var mon = getGroupByIndex("本期应还款([^，]*?)，", description, 1);
                install_month = parseInt(inntall);
                current_month =install_month - (StringUtils.isNotEmpty(getGroupByIndex("余期为(\\d+)期", description, 1)) ? parseInt(getGroupByIndex("余期为(\\d+)期", description, 1)) : 0);
                //exp.setAmountMoney(new BigDecimal(mon.replaceAll(",", "")));
                amountMoney = new BigDecimal(mon.replaceAll(",", ""))
            } else if (StringUtils.isNotEmpty(inwtall)) {
                var mon = getGroupByIndex(" 账单分期 (\\d+\\.\\d)", description, 1);
                //exp.setAmountMoney(new BigDecimal(mon.replaceAll(",", "")));
                amountMoney = new BigDecimal(mon.replaceAll(",", ""));
            } else if (StringUtils.isNotEmpty(infenqi)){
                amountMoney = new BigDecimal(infenqi.replaceAll(",", ""));
            } else {
                amount_money = getGroupByIndex("document.write\\(billQueryDetail1\\('([^']*?)'\\)\\)", amount_money, 1);
                if(amount_money.isEmpty()){
                    //exp.setAmountMoney(null);
                    amountMoney = null;
                }else{
                    //exp.setAmountMoney(new BigDecimal(amount_money));
                    amountMoney = new BigDecimal(amount_money);
                }
            }
            exp.setAmountMoney(amountMoney);

            //分期金额
            var handingFee = null;
            var tempdesc = description.replaceAll(",","");
            var tempHandFee = getGroupByIndex("手续费(\\d+\\.\\d)", tempdesc, 1);
            if(description.contains("分期") && description.contains("手续费") && StringUtils.isNotBlank(tempHandFee)){
                var mon = getGroupByIndex("手续费(\\d+\\.\\d)", tempdesc, 1);
                handingFee = new BigDecimal(mon.replaceAll(",", ""));
            }

            //将分期数据添加进分期列表，手续费除外
            if(description.contains("分期") && install_month!=null && current_month!=null && !description.contains("账单分期 (分期)")){
                var ins = new Installment();
                ins.setInstallmentDesc(description);//分期描述
                ins.setHandingfeeDesc("");//分期手续费描述
                ins.setBillId(UUID.randomUUID().toString());//分期编号
                ins.setTransDate(yyyyMMdd_PARSER.parse(trans_date));//交易时间
                ins.setPostDate(yyyyMMdd_PARSER.parse(post_date));//记账日期
                ins.setShoppingsheetId(UUID.randomUUID().toString());//消费记录
                ins.setInstallmentType("BILL");//分期类型
                ins.setTransferFee(null);//转账手续费
                ins.setTotalMonth(install_month);//总分期数
                ins.setCurrentMonth(current_month);//当前分期数
                ins.setAmountMoney(amountMoney);//本期金额
                ins.setCurrencyType("CNY");//币种
                ins.setHandingFee(handingFee);//本期手续费
                ins.setTransferfeeDesc("");
                installments.add(ins);
            }
            //币种
            exp.setCurrencyType("CNY");
            //根据描述判断消费类型
            exp.setCategory(classify(description,exp.getAmountMoney()));
            //编号
            exp.setOrderIndex(index++);
            shopping_sheets.add(exp);
        }
        var money = new BigDecimal("0.0");
        for each(var exp in shopping_sheets) {
            //获取交易金额
            var amount = exp.getAmountMoney();
            //判断交易金额是否为正
            if (amount != null && amount.signum() == 1) {
                money = money.add(amount);
            }
        }
        //本期新增款额
        billAllData.setNewCharges(money);
        var payment_money = new BigDecimal("0.0");
        for each(var exp in shopping_sheets) {
            //获取交易金额
            var payment_amount = exp.getAmountMoney();
            //判断交易金额是否为负，如果为负数相加即为本期新增款额
            if (payment_amount!=null && payment_amount.signum() == -1) {
                payment_money = payment_money.add(payment_amount);
            }
        }
        //上期还款金额
        billAllData.setLastPayment(payment_money);
        var cal = Calendar.getInstance();
        cal.setTime(billAllData.getBillDate());
        cal.add(Calendar.MONTH, -1);
        var currdate = cal.getTime();
        var currmoth = yyyy_MM_dd_FORMAT.format(currdate);
        currmoth = currmoth.substring(0, 7);
        var bills = creditCardAllData.getBills();
        for each(var billData in bills) {
            if (StringUtils.isNotBlank(billAllData.getBillMonth()) && currmoth.equals(billData.getBillMonth())) {
                //上期账单金额
                billAllData.setLastBalance(billData.getNewBalance());
            }
        }
        billAllData.setShoppingSheets(shopping_sheets);
        billAllData.setInstallments(installments);
        logger.info("任务【{}】,光大银行信用卡解析已出账单，月份【{}】完成",context.get(LUA_TASK_KEY),bill_moth)
    } catch (e){
        logger.error("任务【{}】,光大银行信用卡解析已出账单，月份【{}】，异常【{}】",context.get(LUA_TASK_KEY),bill_moth,e)
        statCaughtExceptionByJS(context, e);
    }
}

/**
 * 获取list下的某个元素
 * @param scripts
 * @returns {string}
 */
function getDataNodeToString( scripts) {
    var scriptList = scripts.get(0).dataNodes();
    var datanode = scriptList.get(0);
    return datanode.toString();
}

/**
 * 将string类型的值转换为bigdecimal类型
 * @param credit_limit
 * @returns {BigDecimal}
 */
function getstringToBigDecimal( credit_limit) {
    var result = getGroupByIndex("document.write\\(formatCurrency\\('([^']*?)'\\)\\)", credit_limit, 1);
    return new BigDecimal(result);
}

/**
 * 将string类型转换为bigdecimal
 * @param val
 * @returns {BigDecimal}
 */
function getBigDecimalByString( val) {
    //将多余的字段都替换为空并滤空
    val = val.replaceAll(",", "")
        .replaceAll("/RMB", "")
        .replaceAll("人民币：| ", "")
        .replaceAll("美元", "")
        .replaceAll(" ", "")
        .trim();
    var bigDecimal = new BigDecimal(val);
    return bigDecimal;
}

/**
 * 获取未出账单的请求的参数
 * @param unbillHtml
 * @param unbillMap
 * @returns {boolean}
 */
function paraseunbillParams(unbillMap) {
    var unbillHtml = context.get("ceb_unbill_html");
    //判断是否登录
    if (unbillHtml.contains("您目前没有登录，请登录后进行此操作 ")) {
        return false;
    }
    if(unbillHtml.contains("No backend server available for connection")){
        return false;
    }
    //解析未出账单页面
    var unbillDoc = Jsoup.parse(unbillHtml);
    var queryForm = unbillDoc.getElementById("form4");
    //获取请求的参数
    var START_SEQ_NBR = paraseParams(queryForm, "START_SEQ_NBR");
    var START_STMT_DATE = paraseParams(queryForm, "START_STMT_DATE");
    var START_TYPE = paraseParams(queryForm, "START_TYPE");
    var MORE_IND = paraseParams(queryForm, "MORE_IND");
    var ACCT_NBR = paraseParams(queryForm, "ACCT_NBR");
    var ORG = paraseParams(queryForm, "ORG");
    var totalpage = getGroupByIndex("processPagingEvents2\\('form4', '([^']*?)'", unbillHtml, 1);
    var currentPage = getGroupByIndex("currentPage = '([^']*?)'", unbillHtml, 1);
    var isnext = getGroupByIndex("var isnext = '(Y|N)';", unbillHtml, 1);

    unbillMap.put("START_SEQ_NBR", START_SEQ_NBR);
    unbillMap.put("START_STMT_DATE", START_STMT_DATE);
    unbillMap.put("START_TYPE", START_TYPE);
    unbillMap.put("MORE_IND", MORE_IND);
    unbillMap.put("ACCT_NBR", ACCT_NBR);
    unbillMap.put("ORG", ORG);
    unbillMap.put("currentpage", currentPage + "1");
    unbillMap.put("totalpage", totalpage);

    if (isnext.equals("Y")) {
        return true;
    } else {
        return false;
    }
}

/**
 * 获取某元素内的有个字段的value值
 * @param form
 * @param element
 * @returns {*}
 */
function paraseParams(form,  element) {
    var elements = form.select("[name='" + element + "']");
    return elements.get(0).attr("value");
}

/**
 * 判断字符串是否是json格式
 * @param str
 * @returns {boolean}
 */
function strIsJSON(str) {
    if (typeof str == 'string') {
        try {
            var obj=JSON.parseObject(str);
            if(typeof obj == 'object' && obj ){
                return true;
            }else{
                return false;
            }

        } catch(e) {
            return false;
        }
    }
}